package bloggo

import (
	"encoding/json"
	"gitee.com/chunanyong/zorm"
	_ "github.com/go-sql-driver/mysql"
	"github.com/gomodule/redigo/redis"
	"io/ioutil"
	"log"
	"time"
)

const (
	CacheKey = "BLOGGO:"

	// PRE_TAG 高亮标签
	PRE_TAG = "<span style='color:#f47466'>"

	// POST_TAG 高亮标签
	POST_TAG = "</span>"
)

func init() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
}

type conf struct {
	ProjectRootPath string `json:"projectRootPath"`
	Port            string `json:"port"`
	Upload          struct {
		Path        string `json:"path"`
		MaxSize     int64  `json:"maxSize"`
		MaxSizeNote string `json:"maxSizeNote"`
		Url         string `json:"url"`
		UrlNote     string `json:"urlNote"`
	} `json:"upload"`
	Redis struct {
		Address     string `json:"address"`
		Username    string `json:"username"`
		Password    string `json:"password"`
		Database    int    `json:"database"`
		MaxIdle     int    `json:"maxIdle"`
		MaxActive   int    `json:"maxActive"`
		IdleTimeout int    `json:"idleTimeout"`
	} `json:"redis"`
	Mysql struct {
		Dsn                   string `json:"dsn"`
		DriverName            string `json:"driverName"`
		Dialect               string `json:"dialect"`
		MaxOpenConns          int    `json:"maxOpenConns"`
		MaxIdleConns          int    `json:"maxIdleConns"`
		ConnMaxLifetimeSecond int    `json:"connMaxLifetimeSecond"`
		SlowSQLMillis         int    `json:"slowSQLMillis"`
	} `json:"mysql"`
	Jwt struct {
		SignKey       string `json:"signKey"`
		ExpiresAt     int    `json:"expiresAt"`
		ExpiresAtNote string `json:"expiresAtNote"`
	} `json:"jwt"`
	Mail struct {
		Host     string `json:"host"`
		Port     string `json:"port"`
		Username string `json:"username"`
		Password string `json:"password"`
	} `json:"mail"`
	QqLogin struct {
		AppId              string `json:"appId"`
		AppKey             string `json:"appKey"`
		DefaultRedirectUrl string `json:"defaultRedirectUrl"`
		HasUnionid         int    `json:"hasUnionid"`
	} `json:"qqLogin"`
}

var Conf = &conf{}

//01.初始化conf
func init() {
	confBytes, err := ioutil.ReadFile("bloggo.conf.json")
	if err != nil { //默认配置 conf
		confBytes = []byte(`{
  "projectRootPath": "/api",
  "port": "9090",
  "upload": {
    "path": "D:/static/",
    "maxSize": 10,
	"maxSizeNote": "单位MB",
    "url": "http://127.0.0.1:9090/static/",
    "urlNote": "上传后返回的访问链接"
  },
  "redis": {
	"address": "127.0.0.1:6379",
	"username": "",
	"password": "",
	"database": 1,
	"maxIdle": 10,
	"maxActive": 100,
	"idleTimeout": 1800
  },
  "mysql": {
	"dsn": "root:root@tcp(127.0.0.1:3306)/blog?charset=utf8&parseTime=true",
	"driverName": "mysql",
	"maxOpenConns": 50,
	"maxIdleConns": 50,
	"connMaxLifetimeSecond": 600,
	"slowSQLMillis": 0
  },
  "jwt": {
	"signKey": "JWTTokenKeyStr",
	"expiresAt": 86400,
	"expiresAtNote": "token有效期单位(秒) 86400=24小时,2592000=30天"
  },
  "mail": {
    "host": "smtp.qq.com",
    "port": "25",
    "username": "2416206063@qq.com",
    "password": "xxx"
  },
  "qqLogin": {
    "appId": "xxx",
    "appKey": "xxx",
    "defaultRedirectUrl": "https://xiaomy.xyz/oauth/login/qq",
    "hasUnionid": 0
  }
}`)
	}
	_ = json.Unmarshal(confBytes, Conf)
	Log(string(confBytes))
}

//02.初始化缓存链接
var redisClient *redis.Pool

func init() {
	redisClient = &redis.Pool{
		Wait: true,
		//连接方法
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial(
				"tcp",
				Conf.Redis.Address,
				redis.DialUsername(Conf.Redis.Username),
				redis.DialPassword(Conf.Redis.Password),
				redis.DialDatabase(Conf.Redis.Database),
			)
			if err != nil {
				return nil, err
			}
			return c, nil
		},
		//DialContext:     nil,
		//TestOnBorrow:    nil,
		//最大的空闲连接数，表示即使没有redis连接时依然可以保持N个空闲的连接，而不被清除，随时处于待命状态。
		MaxIdle: Conf.Redis.MaxIdle,
		//最大的激活连接数，表示同时最多有N个连接
		MaxActive: Conf.Redis.MaxActive,
		//最大的空闲连接等待时间，超过此时间后，空闲连接将被关闭
		IdleTimeout: time.Duration(Conf.Redis.IdleTimeout) * time.Second,
		//MaxConnLifetime: 0,
	}
}

//03.初始化DBDao dbDao 代表一个数据库,如果有多个数据库,就对应声明多个DBDao
var _ *zorm.DBDao

func init() {
	//自定义zorm日志输出
	//zorm.LogCallDepth = 4 //日志调用的层级
	//zorm.FuncLogError = myFuncLogError //记录异常日志的函数
	//zorm.FuncLogPanic = myFuncLogPanic //记录panic日志,默认使用defaultLogError实现
	zorm.FuncPrintSQL = PrintSQL //打印sql的函数

	//自定义日志输出格式,把FuncPrintSQL函数重新赋值
	//log.SetFlags(log.LstdFlags)
	//zorm.FuncPrintSQL = zorm.FuncPrintSQL

	//自定义主键生成
	//zorm.FuncGenerateStringID=funcmyId

	//Go数据库驱动列表:https://github.com/golang/go/wiki/SQLDrivers

	//dbDaoConfig 数据库的配置.这里只是模拟,生产应该是读取配置配置文件,构造DataSourceConfig
	dbDaoConfig := zorm.DataSourceConfig{
		//DSN 数据库的连接字符串,parseTime=true会自动转换为time格式,默认查询出来的是[]byte数组
		DSN: Conf.Mysql.Dsn,
		//DriverName 数据库驱动名称:mysql,postgres,oci8,sqlserver,sqlite3,go_ibm_db,clickhouse,dm,kingbase,aci,taosSql|taosRestful 和Dialect对应
		//sql.Open(DriverName,DSN) DriverName就是驱动的sql.Open第一个字符串参数,根据驱动实际情况获取
		DriverName: Conf.Mysql.DriverName,
		//Dialect 数据库方言:mysql,postgresql,oracle,mssql,sqlite,db2,clickhouse,dm,kingbase,shentong,tdengine 和 DriverName 对应
		Dialect: Conf.Mysql.Dialect,
		//MaxOpenConns 数据库最大连接数 默认50
		MaxOpenConns: Conf.Mysql.MaxOpenConns,
		//MaxIdleConns 数据库最大空闲连接数 默认50
		MaxIdleConns: Conf.Mysql.MaxIdleConns,
		//ConnMaxLifetimeSecond 连接存活秒时间. 默认600(10分钟)后连接被销毁重建.避免数据库主动断开连接,造成死连接.MySQL默认wait_timeout 28800秒(8小时)
		ConnMaxLifetimeSecond: Conf.Mysql.ConnMaxLifetimeSecond,
		//SlowSQLMillis 慢sql的时间阈值,单位毫秒.小于0是禁用SQL语句输出;等于0是只输出SQL语句,不计算执行时间;大于0是计算SQL执行时间,并且>=SlowSQLMillis值
		SlowSQLMillis: Conf.Mysql.SlowSQLMillis,
		//DefaultTxOptions 事务隔离级别的默认配置,默认为nil
		//DefaultTxOptions: nil,
		//如果是使用分布式事务,建议使用默认配置
		//DefaultTxOptions: &sql.TxOptions{Isolation: sql.LevelDefault, ReadOnly: false},

		//FuncGlobalTransaction seata/hptx全局分布式事务的适配函数,返回IGlobalTransaction接口的实现
		//业务必须调用 ctx,_=zorm.BindContextEnableGlobalTransaction(ctx) 开启全局分布事务
		//FuncGlobalTransaction : MyFuncGlobalTransaction,

		//SQLDB 使用现有的数据库连接,优先级高于DSN
		//SQLDB : nil,

		//DisableTransaction 禁用事务,默认false,如果设置了DisableTransaction=true,Transaction方法失效,不再要求有事务,为了处理某些数据库不支持事务,比如TDengine
		//禁用事务应该有驱动伪造事务API,不应该有orm实现,clickhouse的驱动就是这样做的
		//DisableTransaction :false,
	}
	// 根据dbDaoConfig创建dbDao, 一个数据库只执行一次,第一个执行的数据库为 defaultDao,后续zorm.xxx方法,默认使用的就是defaultDao
	_, _ = zorm.NewDBDao(&dbDaoConfig)
}
